/*
 * Copyright (C) 2010 Charles Norona, Allan Pinero, Christopher Sizelove
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.fau.rifl;
/**
 *
 * @author Allan Pinero, Charles Norona, and Christopher Sizelove
 */
import java.awt.*;
import java.awt.event.*;
//import java.applet.Applet;
import java.awt.image.*;
import javax.swing.*;
import java.awt.geom.*;
//import javax.swing.border.*;
//import javax.swing.JApplet;


/*
 * This applet allows the user to move a texture painted rectangle around the applet
 * window.  The rectangle flickers and draws slowly because this applet does not use
 * double buffering.
 */

public class RIFLMain extends JApplet implements Runnable
{
	static protected Label label;

	Thread t = null;
	Boolean threadSuspended;
	private BluetoothRFCOMM pcServerCOMM;
	private static SMCanvas theCanvas;
	private static Rectangle rect = new Rectangle(0, 0, 50, 50);
	private int displacementX = 0;
	private int displacementY = 0;
	private double rawMagnitude = 0;
	private int width, height;
	private static int positionX = 0;
	private static int positionY = 0;
	int last_x, last_y;
	
	private int x = 0, y = 0;//Test variables

	@Override
	public void init()
	{
		//JPanel bg= new JPanel(new BorderLayout());
		// Border bkg=new CenteredBackgroundBorder();
		setLayout(new BorderLayout());
		theCanvas = new SMCanvas();
		add(theCanvas);
		label = new Label("Drag rectangle around within the area");
		add("South", label);
		pcServerCOMM = new BluetoothRFCOMM();
	}

	// Executed after the applet is created; and also whenever
	// the browser returns to the page containing the applet.
	@Override
	public void start()
	{
		//System.out.println("start(): begin");
		if ( t == null )
		{
			//System.out.println("start(): creating thread");
			t = new Thread( this );
			//System.out.println("start(): starting thread");
			threadSuspended = false;
			t.start();
		}
		else
		{
			if ( threadSuspended )
			{
				threadSuspended = false;
				//System.out.println("start(): notifying thread");
				synchronized( this )
				{
					notify();
				}
			}
		}
		//System.out.println("start(): end");
	}

	// Executed whenever the browser leaves the page containing the applet.
	@Override
	public void stop()
	{
		//System.out.println("stop(): begin");
		threadSuspended = true;
	}

	@Override
	public void run()
	{
		//System.out.println("run(): begin");
		try {
			while (true)
			{
				//System.out.println("run(): awake");

				if(pcServerCOMM != null)
				{
					rawMagnitude = (pcServerCOMM.magnitude * pcServerCOMM.magnitude);

					displacementX = (int)(Math.abs(rawMagnitude)
							* Math.cos(Math.toRadians(pcServerCOMM.bearing - 90))
							* 0.83/**/);//Scale factor
					displacementY = (int)(Math.abs(rawMagnitude)
							* Math.sin(Math.toRadians(pcServerCOMM.bearing - 90))
							* 0.83/**/);//Scale factor
				}


				// Now the thread checks to see if it should suspend itself
				if ( threadSuspended )
				{
					synchronized( this )
					{
						while ( threadSuspended )
						{
							System.out.println("run(): waiting");
							wait();
						}
					}
				}

				//System.out.println("run(): requesting repaint");
				theCanvas.updatePosition();
				//repaint();
				//System.out.println("run(): sleeping");
				t.sleep( 100 );  // interval given in milliseconds
			}
		}
		catch (InterruptedException e) { }

		System.out.println("run(): end");
	}
     private static void createAndShowGUI() {

        JFrame f = new JFrame("RIFL");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        		JApplet applet = new RIFLMain();
		f.add("Center", applet);
		applet.init();
		f.setContentPane(applet);
		f.pack();
		f.setSize(Toolkit.getDefaultToolkit().getScreenSize());
		f.setVisible(true);
		applet.start();

    }

	public static void main(String s[]) 
	{
            SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });

		



	}
 class MainPanel extends JPanel
        {
       public MainPanel()
       {
        setBorder(BorderFactory.createLineBorder(Color.black));
       }

    public Dimension getPreferredSize()
    {
        return new Dimension(250,200);
    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
       // Draw Text
        g.drawString("This is my custom Panel!",10,20);
    }
}




	private class SMCanvas extends Canvas implements MouseListener, MouseMotionListener
	{
		BufferedImage bi;
		Graphics2D big;
                Image img,offscreen;
                //Ellipse2D ellipse;
		// Holds the coordinates of the user's last mousePressed event.
		boolean firstTime = true;
                Dimension ssize;
		//TexturePaint fillPolka, strokePolka;
		Rectangle area;

		// True if the user pressed, dragged or released the mouse outside of the rectangle; false otherwise.
		boolean pressOut = false;
                RiflCircle rc= new RiflCircle();
		public SMCanvas()
		{
			setBackground(Color.white);
			addMouseMotionListener(this);
			addMouseListener(this);
                       img= Toolkit.getDefaultToolkit().createImage("C://plan.jpg");
                      //ellipse= new Ellipse2D.Double(CirPos.x, CirPos.y, CirPos.width, CirPos.height);
		}

		// Handles the event of the user pressing down the mouse button.
		public void mousePressed(MouseEvent e)
		{
			last_x = rc.CirPos.x - e.getX();
			last_y = rc.CirPos.y - e.getY();

			// Checks whether or not the cursor is inside of the rectangle while the user is pressing the mouse.
			if(rc.CirPos.contains(e.getX(), e.getY())) updateLocation(e);
			else {
				RIFLMain.label.setText("First position the cursor on the rectangle and then drag.");
				pressOut = true;
			}
		}

		// Handles the event of a user dragging the mouse while holding down the mouse button.
		public void mouseDragged(MouseEvent e)
		{
			if(!pressOut) updateLocation(e);
			else RIFLMain.label.setText("First position the cursor on the rectangle and then drag.");
		}

		// Handles the event of a user releasing the mouse button.
		public void mouseReleased(MouseEvent e)
		{

			// Checks whether or not the cursor is inside of the rectangle when the user releases the mouse button.
			if(rc.CirPos.contains(e.getX(), e.getY())) updateLocation(e);
			else {
				RIFLMain.label.setText("First position the cursor on the rectangle and then drag.");
				pressOut = false;
			}
		}
		
		// This method required by MouseListener.
		public void mouseMoved(MouseEvent e){}

		// These methods are required by MouseMotionListener.
		public void mouseClicked(MouseEvent e){}
		public void mouseExited(MouseEvent e){}
		public void mouseEntered(MouseEvent e){}

		// Updates the coordinates representing the location of the current rectangle.
		public void updateLocation(MouseEvent e)
		{
                    repaint(last_x,last_y,rc.width+1,rc.height+1);
                        rc.setX(e.getX());
                        rc.setY(e.getY());
			
			/*
			 * Updates the label to reflect the location of the
			 * current rectangle
			 * if checkRect returns true; otherwise, returns error message.
			 */
			if (checkRect()) 
			{
				RIFLMain.label.setText("Rectangle located at " +
						rc.CirPos.getX() + ", " +
						rc.CirPos.getY());
			}
			else 
			{
				RIFLMain.label.setText("Please don't try to "+
				" drag outside the area.");
			}

			repaint();
		}

		@Override
		public void paint(Graphics g)
		{
			update(g);
		}

		/**
		 * Applies some graphics and shapes settings so that the elements can be drawn
		 * or redrawn accordingly.
		 */
		@Override
		public void update(Graphics g)
		{
                       
			Graphics2D g2 = (Graphics2D)g;
			g2.setStroke(new BasicStroke(8.0f));
                         g2.drawImage(offscreen(img),0,0,null);
                         rc.paintOval(g2);

		}
  class RiflCircle{

    private int xPos = 0;
    private int yPos = 0;
    private int width = 50;
    private int height = 50;
    private Rectangle CirPos=new Rectangle(xPos,yPos,width,height);
    public void setX(int xPos){
        this.CirPos.x = xPos;
    }

    public int getX(){
        return CirPos.x;
    }

    public void setY(int yPos){
        this.CirPos.y = yPos;
    }

    public int getY(){
        return CirPos.y;
    }

    public int getWidth(){
        return CirPos.width;
    }

    public int getHeight(){
        return CirPos.height;
    }

    public void paintOval(Graphics g){
        g.setColor(Color.RED);
        g.fillOval(CirPos.x,CirPos.y,CirPos.width,CirPos.height);
        g.setColor(Color.BLACK);
        g.drawOval(CirPos.x,CirPos.y,CirPos.width,CirPos.height);
    }
        }

		/**
		 * Checks if the rectangle is contained within the applet window.  If the rectangle
		 * is not contained withing the applet window, it is redrawn so that it is adjacent
		 * to the edge of the window and just inside the window.
		 */
                BufferedImage offscreen(Image s)
                {
                    BufferedImage boff;
                    Graphics2D Gbuff;
                    ssize=getSize();
                    boff=(BufferedImage)createImage(ssize.width, ssize.height);
                    Gbuff= boff.createGraphics();
                    Gbuff.drawImage(img, 0, 0, null);
                    return boff;
                }
		boolean checkRect(){

			if (area == null) {
				return false;
			}

			if(area.contains(rc.CirPos.x, rc.CirPos.y, 100, 50)){
				return true;
			}
			int new_x = rc.CirPos.x;
			int new_y = rc.CirPos.y;

			if((rc.CirPos.x + 100)>area.getWidth())
			{
				new_x = (int)area.getWidth() - 99;
			}
			if(rc.CirPos.x < 0){
				new_x = -1;
			}
			if((rc.CirPos.y + 50)>area.getHeight())
			{
				new_y = (int)area.getHeight() - 49;
			}
			if(rc.CirPos.y < 0){
				new_y = -1;
			}
			rc.CirPos.setLocation(new_x, new_y);
			return false;
		}
		
		/**
		 * Use this function to update the position of shapes and redraw the canvas.
		 */
		public void updatePosition()
		{
			//Update shape's position here
			//x++;
			//y++;
			rc.CirPos.setLocation(rc.CirPos.x + x + displacementX, rc.CirPos.y + y + displacementY);
			repaint();
		}
	}
}




